/*
 * Copyright 2013 Glassy Cinema.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package hu.glassy.web.panel.account.edit;

import hu.glassy.core.model.Account;
import hu.glassy.core.service.AccountService;
import hu.glassy.web.auth.ApplicationSession;
import hu.glassy.web.component.common.CustomAjaxSubmitLink;
import hu.glassy.web.component.feedback.CustomFeedbackPanel;
import hu.glassy.web.component.visitor.ErrorMessageFormVisitor;
import hu.glassy.web.error.ActivationTokenException;
import hu.glassy.web.panel.common.CustomPanel;
import hu.glassy.web.util.PasswordHelper;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;

/**
 * Ezen a panelen tudja megváltoztatni a felhasználó a jelszavát
 *
 * @author molnar.alexander@sonrisa.hu
 */
public class ChangePasswordPanel extends CustomPanel<Account>
{

  private static final long serialVersionUID = -8399365309072378039L;

  @SpringBean
  private AccountService accountService;

  /**
   * Konstruktor
   *
   * @param id
   */
  public ChangePasswordPanel(final String id)
  {
    super(id, Model.of(new Account()));

    Form form = generatePasswordForm();
    add(form);

    form.add(new CustomFeedbackPanel("panelFeedback"));

    Component oldPassword = generateOldPasswordInput();
    form.add(oldPassword);

    FormComponent password = generateNewPasswordInput();
    form.add(password);
    FormComponent cpassword = generateConfirmPasswordInput();
    form.add(cpassword);

    form.add(new EqualPasswordInputValidator(password, cpassword));

    Component submitButton = generateSubmitButton();

    form.visitChildren(new ErrorMessageFormVisitor<String>());
    form.add(submitButton);
  }

  private Form generatePasswordForm()
  {
    return new StatelessForm<Void>("passwordForm")
    {

      @Override
      protected void onSubmit()
      {
        super.onSubmit();

        final Account account = ApplicationSession.get().getAccount().getObject();
        account.setPassword(PasswordHelper.encrypt(ChangePasswordPanel.this.getMainObject().getPassword()));

        try
        {
          accountService.updateAccount(account);
        }
        catch (ActivationTokenException ex)
        {
          // This should not happen because the email addres was not changed
          Logger.getLogger(ChangePasswordPanel.class.getName()).log(Level.SEVERE, null, ex);
        }

        this.clearInput();

        this.success(getString("changepassword.success"));

      }

    };
  }

  private Component generateSubmitButton()
  {
    return new CustomAjaxSubmitLink("submit");
  }

  private FormComponent generateConfirmPasswordInput()
  {
    PasswordTextField confirmInput = new PasswordTextField("confirm", Model.of(""));
    confirmInput.setOutputMarkupId(true);
    confirmInput.setRequired(true);
    confirmInput.setResetPassword(false);
    return confirmInput;
  }

  private FormComponent generateNewPasswordInput()
  {
    PasswordTextField newInput = new PasswordTextField("newpassword", new PropertyModel<String>(ChangePasswordPanel.this.getMainObject(), "password"));
    newInput.setOutputMarkupId(true);
    newInput.setRequired(true);
    newInput.setResetPassword(false);
    return newInput;
  }

  private Component generateOldPasswordInput()
  {
    PasswordTextField oldInput = new PasswordTextField("oldpassword", Model.of(""));
    oldInput.setOutputMarkupId(true);
    oldInput.setRequired(true);
    oldInput.setResetPassword(false);
    oldInput.add(generateOldPasswordValidator());
    return oldInput;
  }

  private IValidator<? super String> generateOldPasswordValidator()
  {
    return new IValidator<String>()
    {
      private static final long serialVersionUID = 1L;

      public void validate(final IValidatable<String> validatable)
      {
        final String password = validatable.getValue();
        final Account account = ApplicationSession.get().getAccount().getObject();

        if (!account.getPassword().equals(PasswordHelper.encrypt(password)))
        {
          validatable.error(new ValidationError(getString("changepassword.error.oldpassword.invalid")));
        }

      }
    };
  }
  // --------------------------------------------------
  // ~ Protected methods
  // --------------------------------------------------
  // --------------------------------------------------
  // ~ Public methods
  // --------------------------------------------------
  // --------------------------------------------------
  // ~ Abstract methods
  // --------------------------------------------------
  // --------------------------------------------------
  // ~ Inner Class
  // --------------------------------------------------
}
